dnl # this file contains definitions of supporting macros for the FileLoader class
include(Resources-T.m4)

m4_divert(-1)
dnl # DEFAULT VALUE DEFINITIONS
dnl # -------------------------

dnl # default value for the separator
m4_ifndef(</SEPARATOR/>, m4_define(</SEPARATOR/>, </|/>))dnl

dnl # default value for the maximum line size
m4_ifndef(</MAX_LINE_SIZE/>, m4_define(</MAX_LINE_SIZE/>, 10000))dnl

dnl # default value for number of tuples in a chunk
m4_ifndef(</TUPLES_PER_CHUNK/>, m4_define(</TUPLES_PER_CHUNK/>, 2000000))dnl

dnl # default value for the size of variable characters
m4_ifndef(</MAX_VARCHAR_SIZE/>, m4_define(</MAX_VARCHAR_SIZE/>, 256))dnl

dnl # HELPING MACROS
dnl # --------------

dnl # macro to extract the name of a column from a colulmn tuple
dnl # $1=column tuple of the form "(name, type)"
m4_define(</M4_COL_NAME/>,</m4_first($1)/>)

dnl # macro to extract the type of a column from a colulmn tuple
dnl # $1=column tuple of the form "(name, type)"
m4_define(</M4_COL_TYPE/>,</m4_second($1)/>)

dnl # macro to define a variable to hold the fix part of a column
dnl # for the variable size data, this is the offset table
dnl # $1=column tuple of the form "(name, type)"
m4_define(</M4_COL_VAR/>, </M4_COL_NAME($1)<//>Data/>)

dnl # macro to define a variable to hold the variable part of a column
dnl # $1=column tuple of the form "(name, type)"
m4_define(</M4_COL_CONTENT/>, </M4_COL_NAME($1)<//>Content/>)

dnl # macro to define a variable to indicate where the next value of a variable column is written
dnl # $1=column tuple of the form "(name, type)"
m4_define(</M4_COL_CURR/>, </M4_COL_NAME($1)<//>Curr/>)


dnl # this macro defines the data for a single column
dnl # $1=column tuple of the form "(name, type)"
m4_define(</M4_DECLARE_COLUMN/>, </dnl
  dnl #if column is of type NONE do nothing		  
  m4_case(M4_COL_TYPE($1), NONE,<//>dnl # column of type NONE so do nothing
              ,VARCHAR,</dnl # the case for variable characters
  
  long int* M4_COL_VAR($1); // offset pointer for column M4_COL_NAME($1)
  char* M4_COL_CONTENT($1); // content of column M4_COL_NAME($1)
     />, </dnl # this is the default behavior
	  
  M4_COL_TYPE($1)* M4_COL_VAR($1); // column M4_COL_NAME($1) array dnl
  />)dnl
/>)dnl

dnl # this macro allocates memory for a column
dnl # $1=column tuple of the form "(name, type)"
m4_define(</M4_ALLOCMEM_COLUMN/>, </dnl
  dnl #if column is of type NONE do nothing		  
  m4_case(M4_COL_TYPE($1), NONE,<//>dnl # column of type NONE so do nothing
              ,VARCHAR,</dnl # the case for variable characters
  
  // allocating memory for  column M4_COL_NAME($1) of type M4_COL_TYPE($1)
  M4_COL_VAR($1)=(long int *) mmap(NULL, bytesToPageAlligned(pageSize, TUPLES_PER_CHUNK*sizeof(long int)), 
		PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 0, 0);
  
  M4_COL_CONTENT($1)=(char*) mmap(NULL, bytesToPageAlligned(pageSize, TUPLES_PER_CHUNK*MAX_VARCHAR_SIZE), 
		       PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 0, 0);
     />, </dnl # this is the default behavior
	  
  M4_COL_VAR($1)=(M4_COL_TYPE($1)*) mmap(NULL, bytesToPageAlligned( pageSize, TUPLES_PER_CHUNK*sizeof(M4_COL_TYPE($1))), 
		  PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 0, 0);
  />)dnl
/>)dnl

dnl # this macro deallocates memory for a column
dnl # $1=column tuple of the form "(name, type)"
m4_define(</M4_FREEMEM_COLUMN/>, </dnl
  dnl #if column is of type NONE do nothing		  
  m4_case(M4_COL_TYPE($1), NONE,<//>dnl # column of type NONE so do nothing
              ,VARCHAR,</dnl # the case for variable characters

  // freeing memory for   column M4_COL_NAME($1) of type M4_COL_TYPE($1)
  munmap(M4_COL_VAR($1), bytesToPageAlligned(pageSize, TUPLES_PER_CHUNK*sizeof(long int)));
  munmap(M4_COL_CONTENT($1),  bytesToPageAlligned(pageSize, TUPLES_PER_CHUNK*MAX_VARCHAR_SIZE));
     />, </dnl # this is the default behavior

  munmap(M4_COL_VAR($1), bytesToPageAlligned( pageSize, TUPLES_PER_CHUNK*sizeof(M4_COL_TYPE($1))));
  />)dnl
/>)dnl


dnl # this macro declares aux variables for filling variable sized columns
dnl # $1=column tuple of the form "(name, type)"
m4_define(</M4_COL_DEFINE_CURR/>, </dnl
  dnl #if column is of type NONE do nothing		  
  m4_case(M4_COL_TYPE($1), VARCHAR,</dnl # the case for variable characters

  // aux variable for column M4_COL_NAME($1)
  char* M4_COL_CURR($1)=M4_COL_CONTENT($1);
     />, </dnl # this is the default behavior
  />)dnl
/>)dnl



dnl # this macro reads the value of a column in the corresponding place
dnl # $1=column tuple of the form "(name, type)"
dnl # $2=position written
dnl # $3=token
m4_define(</M4_COL_FROM_TOKEN/>, </dnl
  dnl #if column is of type NONE do nothing		  
  m4_case(M4_COL_TYPE($1), NONE,</
      // NO CODE NEEDED/>dnl # column of type NONE so do nothing
              ,VARCHAR,</dnl # the case for variable characters

     *(M4_COL_VAR($1)+$2)=(long int)(M4_COL_CURR($1)-M4_COL_CONTENT($1));
     strcpy(M4_COL_CURR($1), $3);
     M4_COL_CURR($1)+=strlen(M4_COL_CURR($1))+1;
     />, </dnl # this is the default behavior

      FromString(*(M4_COL_VAR($1)+$2), $3);
  />)dnl
/>)dnl

dnl # this macro reads the value of a column in the corresponding place
dnl # $1=column tuple of the form "(name, type)"
dnl # $2=columnDescription object
dnl # #3=number of tuples
m4_define(</M4_COL_DESCRIPTION/>, </dnl
  dnl #if column is of type NONE do nothing		  
  m4_case(M4_COL_TYPE($1), NONE,<//>dnl
              ,VARCHAR,</dnl # the case for variable characters

  // record column M4_COL_NAME($1)	      
  {
     ColWriteDescription
       colVar(M4_COL_VAR($1), $3*sizeof(long int), M4_COL_CONTENT($1), 
	   M4_COL_CURR($1)-M4_COL_CONTENT($1), true /** we have offsets not pointers */);
     $2.Append(colVar);
  }
     />, </dnl # this is the default behavior
  
  // record column M4_COL_NAME($1)
  {
	  ColWriteDescription
      colFixed(M4_COL_VAR($1), $3*sizeof(M4_COL_TYPE($1)));
    $2.Append(colFixed);
  }
  />)dnl
/>)dnl

dnl # this macro counts the number of non-NONE columns
dnl # $1=list of columns, each of the form "(name, type)"
m4_define(</M4_NUM_COLS/>,</dnl
m4_define(</M4_NUM_COLS_CNT/>,0)dnl # counter for the columns
m4_foreach(</_C_/>,</$1/>,</dnl
m4_case(M4_COL_TYPE(_C_),NONE,<//>dnl # for NONE we do nothing
,</dnl
dnl # increment the counter 
m4_define(</M4_NUM_COLS_CNT/>,m4_incr(M4_NUM_COLS_CNT)) dnl
/>)dnl
/>)dnl
M4_NUM_COLS_CNT dnl #prints the counter
m4_undefine(</M4_NUM_COLS_CNT/>) dnl # remove the counter for future invocation
/>)dnl
m4_divert(0)dnl
